/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package edu.asu.cse360.service.impl;

import edu.asu.cse360.annotation.TargetEntity;
import edu.asu.cse360.dao.DataAccessObject;
import edu.asu.cse360.model.CustomerSession;
import edu.asu.cse360.model.ItemOrder;
import edu.asu.cse360.model.Order;
import edu.asu.cse360.model.PaymentConfirmation;
import edu.asu.cse360.model.Restaurant;
import edu.asu.cse360.model.Table;
import edu.asu.cse360.service.ItemOrderService;
import edu.asu.cse360.service.OrderService;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service("orderService")
public class OrderServiceImpl implements OrderService{

    @Autowired
    @TargetEntity(Order.class)
    private DataAccessObject<Order, Integer> orderDao;

    @Autowired
    @TargetEntity(PaymentConfirmation.class)
    private DataAccessObject<PaymentConfirmation, Integer> confirmationDao;

    @Autowired
    @TargetEntity(CustomerSession.class)
    private DataAccessObject<CustomerSession, Integer> sessionDao;

    @Autowired
    private ItemOrderService itemOrderService;

    @Override
    public Order placeOrder(Order order, CustomerSession customerSession) {
        assertOrderIsValid(order);
        saveSession(customerSession);
        createOrder(order, customerSession);
        order.setSession(customerSession);
        return order;
    }

    private void assertOrderIsValid(Order order) {
        if(order.getId() != null){
            throwInvalidOrderException("It has already been placed.");
        }
        if(order.getItemOrders() == null || order.getItemOrders().isEmpty()){
            throwInvalidOrderException("It does not contain any item orders.");
        }
        if(order.getTable() == null){
            throwInvalidOrderException("It is not associated to any table.");
        }
    }

    private void throwInvalidOrderException(String message) {
        throw new IllegalArgumentException("The order you are trying to place is invalid. "+message);
    }

    @Override
    public void saveConfirmation(PaymentConfirmation confirm) {
        if(confirm.getId() == null){
            confirmationDao.create(confirm);
        }else{
            confirmationDao.update(confirm);
        }
    }

    private void createOrder(Order order, CustomerSession customerSession) {
       Table table = order.getTable();
       Restaurant restaurant = table.getRestaurant();
       List<ItemOrder> itemOrders = order.getItemOrders();
       for(ItemOrder itemOrder : itemOrders){
           itemOrder.setOrderTime(new DateTime());
           itemOrder.setRestaurant(restaurant);
           itemOrder.setCustomerSession(customerSession);
           itemOrderService.save(itemOrder);
       }
       order.setCreatedTime(new DateTime());
       orderDao.create(order);
    }

    private void saveSession(CustomerSession customerSession) {
        if(customerSession.getId() == null){
            sessionDao.create(customerSession);
        }else{
            sessionDao.update(customerSession);
        }
    }

    @Override
    public boolean validConfirmation(String confirmationKey) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("confirmationKey", confirmationKey);
        PaymentConfirmation confirmation = confirmationDao.findSingleResult(PaymentConfirmation.FIND_BY_CONFIRMATION_KEY, params);
        return confirmation != null;
    }
}
